﻿/*
 * Copyright 2013 Shaun McCloud
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/ 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;

namespace Library
{
    public static class Serialization
    {
        /// <summary>
        /// Deserialize a string into an instance of this class
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static T DeserializeFromXmlString<T>(string xml, T obj)
        {
            MemoryStream ms = null;
            try
            {
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xml);
                ms = new MemoryStream(bytes);

                XmlSerializer xmlReader = new XmlSerializer(typeof(T));
                obj = (T)xmlReader.Deserialize(ms);
                return obj;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (ms != null)
                {
                    ms.Close();
                }
            }
        }

        /// <summary>
        /// Serialize an object into an XML string
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string SerializeToXmlString<T>(T obj)
        {
            try
            {
                string xmlString = null;
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(typeof(T));
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
                xs.Serialize(xmlTextWriter, obj);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                xmlString = Utf8ByteArrayToString(memoryStream.ToArray()); return xmlString;
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
        /// </summary>
        /// <param name="characters">Unicode Byte Array to be converted to String</param>
        /// <returns>String converted from Unicode Byte Array</returns>
        private static string Utf8ByteArrayToString(byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            string constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        /// <summary>
        /// Serialize this class to an xml file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="fileName"></param>
        /// <remarks></remarks>
        public static void SerializeAsXml<T>(T obj, string fileName)
        {
            fileName = GetFullFilename(fileName);

            XmlWriter writer = null;
            try
            {
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                XmlWriterSettings writerSettings = new XmlWriterSettings();
                XmlSerializerNamespaces serializerNamespaces = new XmlSerializerNamespaces();
                StreamWriter streamWriter = new StreamWriter(fileName);

                //create no namespace info so no namespace info will be put in the XML file
                serializerNamespaces.Add("", "");

                //do not add the <?xml...> to the top of the file
                {
                    writerSettings.OmitXmlDeclaration = false;
                    writerSettings.Indent = true;
                    writerSettings.CloseOutput = true;
                    writer = XmlWriter.Create(streamWriter, writerSettings);
                }

                serializer.Serialize(writer, obj, serializerNamespaces);

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if ((writer != null))
                {
                    writer.Close();
                }
            }
        }

        /// <summary>
        /// Deserialize a file into an instance of this class
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static T DeserializeFromXml<T>(string fileName, T obj)
        {
            fileName = GetFullFilename(fileName);

            System.IO.StreamReader reader = null;
            try
            {
                reader = new StreamReader(fileName);
                System.Xml.Serialization.XmlSerializer xmlReader = new System.Xml.Serialization.XmlSerializer(typeof(T));
                obj = (T)xmlReader.Deserialize(reader);
                return obj;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if ((reader != null))
                {
                    reader.Close();
                }
            }
        }

        private static string GetFullFilename(string fileName)
        {
            if (!fileName.Contains("\\"))
            {
                return Directory.GetCurrentDirectory() + "\\" + fileName;
            }
            else
            {
                return fileName;
            }
        }
    }
}